<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/9/19
 * Time: 19:56
 */
namespace app\common\lib;

class NestedCategory
{
    private $db;
    private $tree; //保存结果树
    /**
     * 连接数据库什么的
     */
    function __construct()
    {
        $this->db = new mysqli(config("database.hostname"), config("database.username"), config("database.password"),config("database.database"));
    }

    /**
     * 根据id获取整棵树
     * @param int $id
     * @return array|flase
     */
    function getTreeByRootID($id)
    {
        $query = "select lft,rgt from nestedCategory where id = $id";
        $res   = $this->db->query($query);
        if($res->num_rows<=0){ //查找的根节点树不在
            return false;
        }
        $row = $res->fetch_assoc();
        $lft = $row['lft']; //获取左值
        $rgt = $row['rgt']; //获取右值
        $arrayRight = array(); //记录每个节点的又值便于分出父子关系

        $query = "select * from nestedCategory where lft>=$lft and rgt <= $rgt order by lft ";
        $res   = $this->db->query($query);
        for($i=0;$i<$res->num_rows;$i++){
            $row = $res->fetch_assoc();

            while(!empty($arrayRight)&&end($arrayRight)<$row['rgt']){ //相邻的两条记录的右值第一条的右值比第二条的大那么就是他的父类
                //不是父类出栈
                array_pop($arrayRight);
            }

            $tiltle = $row['title'];
            if(!empty($arrayRight)){
                //$tiltle = '|-'.$tiltle;
            }

            //这里设置节点在树中的层数没有- 表示 根节点
            $this->tree[] = array('title'=>str_repeat('-', count($arrayRight)).$tiltle);
            $arrayRight[] = $row['rgt'];
        }
        return $this->tree;
    }

    /**
     * 为某个父节点添加一个子节点
     * //这里一般创建存储过程
     * @param int $parentId
     * @param int $selfId
     * @param string $title
     */
    function addNodeByPid($parentId,$selfId,$title='default')
    {
        $query = "select lft from nestedCategory where id = $parentId";
        $res   = $this->db->query($query);
        if($res->num_rows<=0){
            return false;
        }
        $row   = $res->fetch_assoc();
        $lft   = $row['lft'];

        //更新左值大于该父节点左值的值
        $query = "update nestedCategory set lft = lft+ 2 where lft>$lft";
        $res = $this->db->query($query);
        if(!$res){
            return false;
        }

        //更新右值大于该父节点左值的值
        $query = "update nestedCategory set rgt = rgt+ 2 where rgt>$lft";
        $res   = $this->db->query($query);
        if(!$res){
            return false;
        }

        //插入节点
        $query = "insert into nestedCategory values($selfId,'".$title."',".($lft+1).','.($lft+2).')';
        $res   = $this->db->query($query);
        if(!$res){
            return FALSE;
        }
        return true;
    }

    /**
     * 删除一棵树
     * @param int $id
     */
    function deleteNodeById($id)
    {
        //
        $query = "select lft,rgt from nestedCategory where id = $id ";
        $res   = $this->db->query($query);
        if($res->num_rows<=0){
            return false;
        }
        $row   = $res->fetch_assoc();
        $dis   = $row['rgt']-$row['lft']+1;

        //删除树
        $query = "delete from nestedCategory where lft>=".$row['lft']." and lft<=".$row['rgt']; //删除左值在lft和rgt之间的结点，包括自己
        $res   = $this->db->query($query);
        if(!$res){
            return false;
        }

        //更新其他结点
        $query = "update nestedCategory set lft=lft-$dis where lft>".$row['rgt'];//更新左值
        $res   = $this->db->query($query);
        if(!$res){
            return false;
        }

        $query = "update nestedCategory set rgt=rgt-$dis where rgt>".$row['rgt'];//更新右值
        $res   = $this->db->query($query);
        if(!$res){
            return false;
        }
        return true;
    }

    /**
     * 输出树形结构
     * @param array $arrayList
     */
    function displayTree(array $arrayList)
    {
        foreach ($arrayList as $list){
            if(is_array($list)){
                foreach ($list as $val){
                    echo $val,'<br/>';
                }
            }else{
                echo $list,'<br/>';
            }
        }
    }
}
